/** @file zipper.h
	@brief Compressed folder handler */

#ifndef G3_ZIPPER_H
#define G3_ZIPPER_H

#include <string.h>
#include <sys/stat.h>
#include <time.h>

#include "zip/unzip.h"
#include "zip/zip.h"

#include "types.h"
#include "log.h"
#include "text.h"

namespace G3 {

/** @class ZIPPER
	@brief Compressed folder handler */
class ZIPPER {
    public:
        /**
            Some kind of a constructor
        */
		ZIPPER ();

        /** A file decompressor */
		unzFile Decompressor;
        /** A file compressor */
		zipFile Compressor;

		/** Pointer to the log */
		LOG *log;

        /** Status variable */
		bool FileSuccessfullyLoaded;
		/** Whether the file paths are case insensitive or not */
		bool CaseInsensitive;

//==============================================================================
// Opens a Zip file
//
//  flags: w      Open for writing
//         r      Open for reading
//         s      SFX package mode
//  If none, the function just checkes for the Zip file existence
//==============================================================================
        /**
            @brief Opens a Zip file
            @param[in] filename Reference to the compressed folder to be opened
            @param[in] flags Open flags:<br>
            <b>w</b> - Open for writing,<br>
            <b>r</b> - Open for reading,<br>
            <b>s</b> - SFX package mode<br>
            If none, the function just checks for the Zip file existence.
            @return True on success, false on failure
        */
        bool Open (const string &filename, const string &flags);

        /**
            @brief Inserts data as a file into the Zip file
            @param[in] filename Reference to the file path in the Zip
            @param[in] data Pointer to the data to be written into the file
            @param[in] size Number of bytes to be written
            @param[in] compression Compression level
            @return True on success, false on failure
        */
        bool Write (const string &filename, byte *data, ulong size, int compression = Z_DEFAULT_COMPRESSION);

        /**
            @brief Inserts a file into the Zip file
            @param[in] filename Reference to the file path
            @param[in] destination Reference to the file path inside the Zip file
            @param[in] compression Compression level
            @return True on success, false on failure
        */
        bool InsertFile (const string &filename, const string &destination = NULL, int compression = Z_DEFAULT_COMPRESSION);

        /**
            @brief Gets data from a file in the Zip file
            @param[in] filename Reference to the file path inside the Zip file
            @param[out] data Pointer to the memory block for written data
            @param[in] size Number of bytes to read
            @return Pointer to the data
        */
        byte *Read (const string &filename, byte *data, ulong *size);

        /**
            @brief Gets a file from the Zip
            @param[in] src Reference to the path of the file in the Zip
            @param[in] dest Reference to the path of the file outside the Zip
            @return True on success, false on failure
        */
        bool GetFile (const string &src, const string &dest);

        /**
            @brief Checks if the zip file contains a file
            @param[in] filename Reference to the file path inside the Zip that is to be checked
            @return True if the Zip really does contain that file and false if it doesn't
        */
		bool ContainsFile (const string &filename);

        /**
            @brief Gets the uncompressed size of a file in the zip
            @param[in] filename Reference to the file path inside the Zip
            @return Size of the file or 0 if the file doesn't exist
        */
		long GetFileSize (const string &filename);

        /**
            @brief Closes the Zip file and saves all changes
            @return True on success and false on failure
        */
        bool Close ();
};

/** Prototype for the file existence check */
bool FileExists (const string &filename);

}

#endif //G3_ZIPPER_H
